package com.dhcc.service;

import com.dhcc.entity.ClientUser;
import com.dhcc.entity.SysUser;
import com.dhcc.jwt.JwtTokenUtil;
import com.dhcc.utils.AuthUtil;
import com.dhcc.utils.PasswordEncoderUtil;
import io.jsonwebtoken.Claims;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @ProjectName Dhcc-Cloud
 * @PackageName com.dhcc.service
 * @Title AuthService
 * @Date 2024/12/18 22:17
 * @Author LiuGuoting
 */
@Service
public class AuthService {
    @Resource
    private SysUserService sysUserService;
    @Resource
    private ClientUserService clientUserService;
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    @Resource
    private RedisService redisService;
    /**
     * 设置新的令牌的过期时间：60 分钟
     */
    // private final long expireTime = 305L;
    private final long expireTime = 3600L;
    /**
     * 设置令牌过期时间的单位：秒
     */
    private final TimeUnit timeUnit = TimeUnit.SECONDS;

    public Map<String, Object> login(String username, String password, AuthenticationManager authenticationManager,String loginType) {
        // 创建基于用户名和密码的身份验证 Token
        UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username, password);
        // 进行身份认证
        Authentication authentication = authenticationManager.authenticate(auth);
        // 从认证对象中获取用户详情
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        if (userDetails.getUsername()== null) {
            return null;
        }
        // 如果认证成功，将认证信息保存到 SecurityContext 中
        SecurityContextHolder.getContext().setAuthentication(authentication);

        String jwtToken = null;
        String userName = null;
        if(loginType.equals("system")){
            // 客户端登录
            SysUser user = sysUserService.getUserByUsername(userDetails.getUsername());
            userName = user.getUserName();
            // 创建 JWT 令牌的自定义载荷
            Map<String, Object> claims = new HashMap<>();
            // 添加用户ID到 JWT 令牌的自定义载荷中
            claims.put("userId", user.getId());
            // 添加用户名到 JWT 令牌的自定义载荷中
            claims.put("userName", user.getUserName());
            // 生成 JWT 令牌
            jwtToken = jwtTokenUtil.generateToken(claims);
        }else if(loginType.equals("client")){
            // 客户端登录
            ClientUser user = clientUserService.getUserByUsername(userDetails.getUsername());
            userName = user.getUserName();
            // 创建 JWT 令牌的自定义载荷
            Map<String, Object> claims = new HashMap<>();
            // 添加用户ID到 JWT 令牌的自定义载荷中
            claims.put("userId", user.getId());
            // 添加用户名到 JWT 令牌的自定义载荷中
            claims.put("userName", user.getUserName());
            // 生成 JWT 令牌
            jwtToken = jwtTokenUtil.generateToken(claims);
        }
        // 将令牌存入Redis缓存中
        redisService.setCacheObject(userName+"@token",jwtToken,expireTime, timeUnit);
        // // // 将可访问接口权限存入Redis缓存中
        List<String> authList = new ArrayList<>();
        //
        authList.add("/sys/userInfo");
        authList.add("/sys/getSysLoginDept");
        authList.add("/sys/getSysLoginPosition");
        authList.add("/sys/deptAndPositionLogin");
        //客户端接口权限
        authList.add("/userSystem/getInstitutionList");
        authList.add("/userSystem/getInstitutionRoles");
        authList.add("/userSystem/getDepartment");
        authList.add("/userSystem/getPosition");
        authList.add("/userSystem/getFinanceList");
        authList.add("/userSystem/getUserInfo");
        authList.add("/userSystem/sys/client/resource/getListTree");
        authList.add("/userSystem/user/selectUserListByInstitutionId");
        authList.add("/userSystem/user/addUserByInstitutionId");
        authList.add("/userSystem/user/deleteUserByUserId");
        authList.add("/userSystem/user/updateUserByUserId");
        authList.add("/userSystem/user/selectUserByUserIdAndInstitutionId");
        authList.add("/userSystem/clientDepartment/getDepartmentList");
        authList.add("/userSystem/clientPosition/getPositionNameList");
        authList.add("/userSystem/institution/selectInstitution");
        authList.add("/userSystem/institution/selectChildInstitutionList");
        authList.add("/userSystem/institution/selectInstitutionAndAdminInfo");
        authList.add("/userSystem/institution/addInstitutionAndAdmin");
        authList.add("/userSystem/institution/updateInstitution");
        authList.add("/userSystem/clientDepartment/selectDepartmentList");
        authList.add("/userSystem/clientDepartment/getDepartmentInfo");
        authList.add("/userSystem/clientDepartment/addDepartment");
        authList.add("/userSystem/clientPosition/getPositionNameList");
        authList.add("/userSystem/clientPosition/selectPositionList");
        authList.add("/userSystem/clientPosition/addPosition");
        authList.add("/userSystem/clientPosition/deletePosition");
        authList.add("/userSystem/clientPosition/selectPositionInfo");
        authList.add("/userSystem/clientPosition/updatePosition");
        authList.add("/userSystem/resource/selectResourceList");
        authList.add("/userSystem/resource/addResource");
        authList.add("/userSystem/resource/updateResource");
        authList.add("/userSystem/resource/deleteResource");
        authList.add("/userSystem/clientDepartment/selectDepartmentListTree");
        authList.add("/userSystem/clientDepartment/deleteDepartment");
        authList.add("/userSystem/clientDepartment/updateDepartment");
        authList.add("/userSystem/resource/selectParentResourceList");
        authList.add("/userSystem/resource/getResourceInfo");
        authList.add("/userSystem/institution/getAllInstitutionRole");
        authList.add("/userSystem/file/uploadUrl");
        authList.add("/userSystem/file/download");
        authList.add("/userSystem/file/delete");
        authList.add("/userSystem/institution/deleteInstitution");
        authList.add("/userSystem/clientPosition/resourceAllocation");
        authList.add("/userSystem/clientPosition/getAllResourceList");
        authList.add("/userSystem/clientPosition/getAlreadyAllocationResourceIds");
        redisService.setCacheObject(userName+"@auth",authList,expireTime, timeUnit);
        // 返回成功地响应，包含 JWT 令牌
        Map<String, Object> data = new HashMap<>();
        // 添加令牌类型到响应数据中
        data.put("tokenType", "bearer");
        // 添加 JWT 令牌到响应数据中
        data.put("access_token", jwtToken);
        // 添加 JWT 令牌的过期时间(时间戳)到响应数据中
        data.put("expireTime", jwtTokenUtil.getTokenExpiration(jwtToken).getTime());
        return data;
    }


    public Map<String, Object> refreshToken() {
        String token = AuthUtil.getToken();
        // 刷新 JWT 令牌
        String newToken = jwtTokenUtil.refreshToken(token);
        // token中获取用户名
        Claims claims = JwtTokenUtil.extractClaims(token);
        String userName = claims.getSubject();
        // 比对接收到的token和redis中的token是否一致
        String redisToken = redisService.getCacheObject(userName+"@token").toString();
        if (!redisToken.equals(token)) {
            return null;
        }
        // 从redis中删除旧的令牌
        redisService.deleteObject(userName+"@token");
        // 将令牌存入Redis缓存中(KV{Token，UserName})
        redisService.setCacheObject(userName+"@token",newToken,expireTime, timeUnit);
        //刷新可访问接口权限的缓存过期时间
        redisService.expire(userName+"@auth",expireTime, timeUnit);
        // 刷新可访问资源树的缓存过期时间
        redisService.expire(userName+"@resource",expireTime, timeUnit);
        // 返回成功地响应，包含 JWT 令牌
        Map<String, Object> data = new HashMap<>();
        // 添加令牌类型到响应数据中
        data.put("tokenType", "bearer");
        // 添加 JWT 令牌到响应数据中
        data.put("access_token", newToken);
        // 添加 JWT 令牌的过期时间到响应数据中
        data.put("expireTime", jwtTokenUtil.getTokenExpiration(newToken).getTime());
        return data;
    }
    public boolean logout() {
        String token = AuthUtil.getToken();
        Claims claims = JwtTokenUtil.extractClaims(token);
        String userName = claims.getSubject();
        // 比对接收到的token和redis中的token是否一致
        String redisToken = redisService.getCacheObject(userName+"@token").toString();
        if (!redisToken.equals(token)) {
            return false;
        }
        // 根据 userName 删除对应的缓存
        redisService.deleteObject(userName+"@token");
        redisService.deleteObject(userName + "@auth");
        redisService.deleteObject(userName + "@resource");
        return true;
    }
}
